/**
 * 线图生成类
 * @param parent 父组件dom对象
 * @param config 图形的配置对象
 * <br>
 * <br>dataset : Y轴数据数组，[{"2012-1-1" : number, "2012-1-2" : number...},...]
 * <br>xMarks : X轴数据数组，一维数组
 * <br>seriesNames : 系列名称，数组
 * <br>seriesColors : 系列颜色，数组
 * <br>xAxisType X轴类型：catagory(分类),date(日期)
 * <br>xAxisSortType : x轴排序方式:asc,desc
 * <br>showPointMarker : 是否显示数据点
 * <br>title : 标题,字符串
 * <br>subtitle : 子标题,字符串
 */

/*
* Microsecond support
*/
if (!Date.prototype.getMicroseconds) {
	Date.prototype.microseconds = 0;
	Date.prototype.getMicroseconds = function () { return this.microseconds; };
	Date.prototype.setMicroseconds = function (m) {
		this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));
		this.microseconds = m % 1000;
		return this;
	};
}
function GroupLineChart(parent, config) {
	config = config || {};
	var container = $(parent);
	
	var oldDataset = config.dataset || [];

 	if(oldDataset.length == 0) {
 		return;
 	}
 	
 	//最大值，最小值，最大限制值，最小限制值
 	var maxdata, mindata, maxLimit, minLimit;
 	
	var xAxisType = config.xAxisType || "catagory";
	//x轴排序方式
	var xAxisSortType = config.xAxisSortType || "asc";
	

 	var xAdapter = null;
 	
 	if(xAxisType == "date") {
 		xAdapter = new DateAdapter({
 			oldDataset : oldDataset,
 			timeFormat : config.timeFormat || "year",
 			isXAsc : config.xAxisSortType == "asc"
 		});
 	} else if(xAxisType == "catagory") {
 		xAdapter = new CatagoryAdapter({
 			oldDataset : oldDataset,
 			isXAsc : true
 		});
 	}
	
	var xAxisTitle = config.xAxisTitle || ('X'+TempoUtils.locale("mine.zhou"));
	var yAxisTitle = config.yAxisTitle || ('Y'+TempoUtils.locale("mine.zhou"));
	
	var yTicksLength = 10;
	//轴标签文字的最大长度，超过此长度使用...替代
	var legendLabelMaxLength = 6;
	
	var showPointMarker = !!config.showPointMarker;
	
	xAdapter.changeDataset();
	//将原来的数据格式改造为key，value式的格式，便于调用
	var dataset = xAdapter.newDataset;
	
 	var _lines = []; //保存折线图对象
 	var xMarks = config.xMarks || [];//X轴的标签
 	var seriesNames = config.seriesNames || []; //保存系列名称
 	var seriesColors = config.seriesColors || ["#F00","#09F","#0F0"];
 	
 	var w = container.width();
 	var h = container.height();
 	var padding=40;
 	var currentLineNum=0;
 	
 	//用一个变量存储标题和副标题的高度，如果没有标题什么的，就为0
 	var head_height = padding;
 	var title = config.title || "";
 	var subTitle= config.subtitle || "";
 	 
 	//用一个变量计算底部的高度，如果不是多系列，就为0
 	var foot_height = padding;
 	
 	var left_padding = padding;
 	
 	//保存数组长度，也就是系列的个数
 	currentLineNum = dataset.length;
 	 
 	//定义画布
 	var svg = d3.select(parent).append("svg")
 		.attr("width",w).attr("height",h);
 	 
 	//添加背景
 	svg.append("g").append("rect")
	 	.attr("x",0).attr("y",0)
	 	.attr("width",w).attr("height",h)
	 	.style("fill","#FFF").style("stroke-width",2).style("stroke","#E7E7E7");
 	 
 	//添加标题
 	if(title!="")
 	{
	 	svg.append("g").append("text").text(title).attr("class","gl_title")
	 		.attr("x",w/2).attr("y",head_height);
	 	 
	 	head_height+=30;
 	}
 	 
 	//添加副标题
 	if(subTitle!="")
 	{
	 	svg.append("g").append("text").text(subTitle).attr("class","gl_subTitle")
	 		.attr("x",w/2).attr("y",head_height);
	 	 
	 	head_height+=20;
 	}
 	
 	updateMaxMin(dataset);

 	//获取分组列信息
	var seriesColumnName = config.seriesColumnName;
 	//添加图例
 	var legend=svg.append("g");
	if (seriesColumnName != null) {
		addLegend();
	}
	//给图例预留位置
	head_height += 25;
 	
 	//为X标题预留位置
	foot_height += 16;
	left_padding = left_padding + 16;
	
	var yTitle = svg.append("text").text(yAxisTitle).attr("text-anchor", "middle")
		.attr("y", padding + "px")
		.attr("dy", "-1em")
		.attr("x", -(head_height + (h - head_height - foot_height) / 2) + "px")
		.attr("transform", "rotate(-90)")
		.attr("class", "gl_axis_title");
	
	
 	//纵坐标轴比例尺
 	var yScale = d3.scale.linear()
 		.domain([minLimit, maxLimit]).range([h - foot_height, head_height]);
 	 
 	var yTicks = yScale.ticks(yTicksLength);
 	if(yTicks.length > 0) {
 		var maxYLabelLength = d3.max([(yTicks[0] + "").length, (yTicks[yTicks.length - 1] + "").length]);
 		//假设一个数字是7像素
 		left_padding += maxYLabelLength * 7;
 	}
 	
 	var xTitle = svg.append("text").text(xAxisTitle).attr("text-anchor", "middle")
	.attr("x", (left_padding + (w - left_padding - padding) / 2) + "px").attr("y", (h - foot_height + 16) + "px").attr("dy", "2em").attr("class", "gl_axis_title");
	
	
 	xAdapter.initXAxisElements([left_padding, w - padding]);
 	
 	//横坐标轴比例尺
 	var xScale = xAdapter.xScale;
 	var xLabelFormat = xAdapter.xFormatter;
 	var xAxisValues = xAdapter.xAxisValues;
 	 
 	//定义横轴网格线
 	var xInner = d3.svg.axis()
	 	.scale(xScale)
	 	.tickSize(-(h - head_height - foot_height),0,0)
	 	.tickFormat("")
	 	.orient("bottom")
	 	.tickValues(xAxisValues);
 	 
 	//添加横轴网格线
 	var xInnerBar=svg.append("g")
	 	.attr("class","gl_inner_line")
	 	.attr("transform", "translate(0," + (h - foot_height) + ")")
	 	.call(xInner);
 	 
 	//定义纵轴网格线
 	var yInner = d3.svg.axis().scale(yScale)
	 	.tickSize(-(w - left_padding - padding),0,0)
	 	.tickFormat("")
	 	.orient("left")
	 	.ticks(yTicksLength);
 	 
 	//添加纵轴网格线
 	var yInnerBar=svg.append("g").attr("class", "gl_inner_line")
	 	.attr("transform", "translate("+left_padding+",0)")
	 	.call(yInner);
 	 
 	//定义横轴
 	var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickValues(xAxisValues);
 	 
 	//添加横坐标轴
 	var xBar=svg.append("g")
	 	.attr("class","gl_axis")
	 	.attr("transform", "translate(0," + (h - foot_height) + ")")
	 	.call(xAxis);
 	//通过编号获取对应的横轴标签
 	xBar.selectAll("text").text(function(d, i){
 		return xLabelFormat(d);
 	});
 	 
 	//定义纵轴
 	var yAxis = d3.svg.axis()
	 	.scale(yScale)
	 	.orient("left")
	 	.ticks(yTicksLength);
 	 
 	//添加纵轴
 	var yBar=svg.append("g")
	 	.attr("class", "gl_axis")
	 	.attr("transform", "translate("+left_padding+",0)")
	 	.call(yAxis);
 	 
 	//添加折线
 	_lines=[];
 	for(i=0;i<currentLineNum;i++)
 	{
	 	var newLine=new CrystalLineObject();
	 	newLine.init(i);
	 	_lines.push(newLine);
 	}
 	
 	//定义折线类
	function CrystalLineObject()
	{
		this.group=null;
		this.path=null;
		 
		this.init=function(id)
		{
			var arr=dataset[id];
			this.group=svg.append("g");
			 
			var line = d3.svg.line()
				.x(function(d){
					return xScale(Date.parse(d.key));
				})
				.y(function(d){return yScale(d.value);});
			 
			//添加折线
			this.path=this.group.append("path")
				.attr("d",line(arr))
				.style("fill","none")
				.style("stroke-width",2)
				.style("stroke",seriesColors[id % seriesColors.length])
				.style("stroke-opacity",0.9);
			
			this.group.append("title").text(seriesNames[id]);

			//添加系列的小圆点
			if (seriesColumnName != null) {
				//分组折线图
				this.group.selectAll("circle").data(arr).enter().append("circle")
					.attr("cx", function(d) {
						return xScale(Date.parse(d.key));
					})
					.attr("cy", function(d) {
						return yScale(d.value);
					})
					.attr("r", 3)
					.style("opacity", showPointMarker ? 1 : 0)//将数据点的透明度设为0，为了使用tooltip功能
					.attr("fill",seriesColors[id % seriesColors.length])
					.append("title").text(function(d) {
					return seriesNames[id] + "\n" + "(" + d.key + ", " + d.value + ")"
				});
			}else {
				//单个折线图
				this.group.selectAll("circle").data(arr).enter().append("circle")
					.attr("cx", function(d) {
						return xScale(Date.parse(d.key));
					})
					.attr("cy", function(d) {
						return yScale(d.value);
					})
					.attr("r", 3)
					.style("opacity", 0)//将数据点的透明度设为0，为了使用tooltip功能
					.attr("fill",seriesColors[id % seriesColors.length])
					.append("title").text(function(d) {
					return "(" + d.key + ", " + d.value + ")"
				});
			}

		
		};
		//从画布删除折线
		this.remove=function()
		{
			this.group.remove();
		};
	}
	
 	//添加图例
 	function addLegend()
 	{
	 	var textGroup=legend.selectAll("g")
	 		.data(seriesNames);
	 	textGroup.exit().remove();
	 	
	 	var lgs = legend.selectAll("g").data(seriesNames).enter().append("g")
		 	.attr("x", function(d,i) {return i*100;})
		 	.attr("y",0);
	 	
	 	lgs.append("rect")
		 	.attr("x", function(d,i) {return i*100-20;})
		 	.attr("y",-10)
		 	.attr("width",12)
		 	.attr("height",12)
		 	.attr("fill",function(d,i){ return seriesColors[i % seriesColors.length];});
	 	
	 	lgs.append("text")
		 	.text(function(d){
		 		if(d.length > legendLabelMaxLength) {
		 			d = d.substring(0, legendLabelMaxLength) + "...";
		 		}
		 		return d;
		 	})
		 	.attr("class","gl_legend")
		 	.attr("x", function(d,i) {return i*100;})
		 	.attr("y",0)
		 	.attr("fill", "#333");
	 	
	 	lgs.append("title").text(function(d){return d;});
	 	 
	 	legend.attr("transform","translate("+((w-seriesNames.length*100)/2)+","+ head_height +")");
 	}
 	
 	function updateMaxMin(dataset) {
 	 	var mmResult = getMaxdata(dataset);
 	 	maxdata = mmResult.max;
 	 	mindata = mmResult.min;
 	 	
 	 	var dlt = (maxdata - mindata) / 10;
 	 	if(dlt == 0) {
 	 		dlt = 1;
 	 	}
 	 	
 	 	maxLimit = maxdata + dlt;
 	 	minLimit = mindata - dlt;
 	}
 	
 	/**
 	 * 字符串X轴适配器
 	 * */
 	function DateAdapter(config) {
 		debugger
 		/**
 		 * 参数区
 		 * */
 		this._isXAsc = config.isXAsc;
 		this._timeFormat = config.timeFormat;
 		this._oldDataset = config.oldDataset;
 		/**
 		 * 数据结果区
 		 */
 		this.newDataset = null;
 		this.allXValue = null;
 		
 		/**
 		 * X轴结果区
 		 */
 		this.xScale = null;
 		this.xAxisValues = null;
 		this.xFormatter = null;
 		
 		this.changeDataset = function() {
 			var allXValue = [];
 			var dataset = [];
 			
 		 	//排序数据集方法
 		 	var sortDatasetFunction = this._isXAsc ? 
 		 			function(a, b) {return a.key < b.key ? -1 : 1;} : 
 		 			function(a, b) {return a.key < b.key ? 1 : -1;};
 		 	
 		    //排序X轴数据数组方法
 		 	
 			for(var di = 0; di < this._oldDataset.length; di ++) {
 				var yArray = this._oldDataset[di];
 				var yMap = [];
 				var keys = [];
 				
 				var keyMap = {};
 				
 				for(var key in yArray) {
 					if(key == "<NULL>" || isNaN(yArray[key])) {
 						//排除掉无用数据
 						continue;
 					}
 					if(keyMap[key] != null) {
 						//排除掉重复数据
 						continue;
 					}
 					keyMap[key] = 123;
 					keys.push(key);
 					yMap.push({key : key, value : parseFloat(yArray[key])});
 				}
 				yMap.sort(sortDatasetFunction);
 				dataset.push(yMap);
 				allXValue.push.apply(allXValue, keys);
 			}
 			
 			this.allXValue = d3.set(allXValue).values();
 			this.allXValue.sort(d3.ascending);
 			
 			this.newDataset = dataset;
 		}
 		
 		/**
 		 * 初始化适配器
 		 * @param allXValue X轴的值序列
 		 * @param rangeArray X轴的序列值
 		 * */
 		this.initXAxisElements = function(rangeArray) {
 			var minDate = new Date(Date.parse(this.allXValue[0]));
 			minDate.setMicroseconds(0);
 			
 			var maxDate = new Date(Date.parse(this.allXValue[this.allXValue.length - 1]));
 			maxDate.setMicroseconds(0);
 			//最小日期限制
 			var minDateLimit = new Date(minDate.getTime());
 			//最大日期限制
 			var maxDateLimit = new Date(maxDate.getTime());
 			
 			var dayMilis = 24 * 60 * 60 * 1000;
 			
 			var xAxisDateValues = [];
 			var xAxisNumberValues = [];

 			var maxLabelLength = 10;
 			var xLabelFormat = null;
 			var dateStep = 1;
 			if(this._timeFormat == "year") {
 				minDateLimit = new Date(minDateLimit.getTime() - dayMilis * 365 / 2);
 				maxDateLimit = new Date(maxDateLimit.getTime() + dayMilis * 365 / 2);
 				dateStep = Math.ceil((maxDateLimit.getFullYear() - minDateLimit.getFullYear()) / maxLabelLength) || 1;
 				for(var jd = new Date(minDateLimit.getTime()); jd.getFullYear() <= maxDateLimit.getFullYear(); jd.setFullYear(jd.getFullYear() + dateStep)) {
 					var tickTime = new Date(jd.getTime());
 					tickTime.setMonth(0);
 					tickTime.setDate(1);
 					if(tickTime.getTime() < minDateLimit.getTime()) {
 						//如果出现第一个时间小于最小时间的情况，走下一个
 						continue;
 					}
 					xAxisDateValues.push(tickTime);
 				}
 				xLabelFormat = function(d) {return DateUtils.formatDate(parseFloat(d), "yyyy");};
 			} else if(this._timeFormat == "month") {
 				minDateLimit = new Date(minDateLimit.getTime() - dayMilis * 15);
 				maxDateLimit = new Date(maxDateLimit.getTime() + dayMilis * 15);
 				
 				dateStep = Math.ceil(((maxDateLimit.getFullYear() * 12 + maxDateLimit.getMonth()) - (minDateLimit.getFullYear() * 12 + minDateLimit.getMonth())) / maxLabelLength) || 1;
 				var jd = new Date(minDateLimit.getTime());
 				jd.setDate(1);
 				for(; jd.getTime() <= maxDateLimit.getTime(); jd.setMonth(jd.getMonth() + dateStep)) {
 					var tickTime = new Date(jd.getTime());
 					if(tickTime.getTime() < minDateLimit.getTime()) {
 						//如果出现第一个时间小于最小时间的情况，走下一个
 						continue;
 					}
 					xAxisDateValues.push(tickTime);
 				}
 				xLabelFormat = function(d) {return DateUtils.formatDate(parseFloat(d), "yyyy-MM");};
 			} else if(this._timeFormat == "day") {
 				minDateLimit = new Date(minDateLimit.getTime() - dayMilis * 1);
 				maxDateLimit = new Date(maxDateLimit.getTime() + dayMilis * 1);
 				
 				dateStep = Math.ceil((maxDateLimit.getTime() - minDateLimit.getTime()) / dayMilis / maxLabelLength) || 1;
 				for(var jd = new Date(minDateLimit.getTime()); jd.getTime() <= maxDateLimit.getTime(); jd.setDate(jd.getDate() + dateStep)) {
 					var tickTime = new Date(jd.getTime());
 					tickTime.setMicroseconds(0);
 					if(tickTime.getTime() < minDateLimit.getTime()) {
 						//如果出现第一个时间小于最小时间的情况，走下一个
 						continue;
 					}
 					xAxisDateValues.push(tickTime);
 				}
 				xLabelFormat = function(d) {return DateUtils.formatDate(parseFloat(d), "yyyy-MM-dd");};
 			}
 			this.xFormatter = xLabelFormat;
 			
 			//x轴的定义域
 			var xDomain = [minDateLimit.getTime(), maxDateLimit.getTime()];
 			//生成X轴刻度的数值数组，用于定位刻度的位置
 			xAxisNumberValues = d3.map(xAxisDateValues, function(d) {return d.getTime();}).keys();

 			if(this._isXAsc == false) {
 				xAxisNumberValues.reverse();
 				xDomain.reverse();
 			}
 			
 			this.xAxisValues = xAxisNumberValues;
 			this.xScale = d3.scale.linear().domain(xDomain).range(rangeArray);
 		}
 	}
 	/**
 	 * 日期X轴适配器
 	 */
 	function CatagoryAdapter(config) {
 		/**
 		 * 参数区
 		 * */
 		this._isXAsc = config.isXAsc;
 		this._oldDataset = config.oldDataset;

 		/**
 		 * 数据结果区
 		 */
 		this.newDataset = null;
 		this.allXValue = null;

 		/**
 		 * X轴结果区
 		 */
 		this.xScale = null;
 		this.xAxisValues = null;
 		this.xFormatter = null;
 		
 		this.changeDataset = function() {
 			var allXValue = [];
 			var dataset = [];
 			
 		 	//排序数据集方法
 		 	var sortDatasetFunction = this._isXAsc ? 
 		 			function(a, b) {return a.key < b.key ? -1 : 1;} : 
 		 			function(a, b) {return a.key < b.key ? 1 : -1;};
 		 	
 		    //排序X轴数据数组方法
 		 	
 			for(var di = 0; di < this._oldDataset.length; di ++) {
 				var yArray = this._oldDataset[di];
 				var yMap = [];
 				var keys = [];
 				
 				var keyMap = {};
 				
 				for(var key in yArray) {
 					if(key == "<NULL>" || isNaN(yArray[key])) {
 						//排除掉无用数据
 						continue;
 					}
 					if(keyMap[key] != null) {
 						//排除掉重复数据
 						continue;
 					}
 					keyMap[key] = 123;
 					keys.push(key);
 					yMap.push({key : key, value : parseFloat(yArray[key])});
 				}
 				yMap.sort(sortDatasetFunction);
 				dataset.push(yMap);
 				allXValue.push.apply(allXValue, keys);
 			}
 			
 			this.allXValue = d3.set(allXValue).values();
 			this.allXValue.sort(this._isXAsc ? d3.ascending : d3.descending);
 			
 			this.newDataset = dataset;
 		}
 		
 		/**
 		 * 初始化适配器
 		 * @param allXValue X轴的值序列
 		 * @param rangeArray X轴的序列值
 		 * */
 		this.initXAxisElements = function(rangeArray) {
 			this.xAxisValues = this.allXValue;
 			this.xScale = d3.scale.ordinal().domain(xDomain).rangePoints(rangeArray);
 			this.xFormatter = function(d) {return d;};
 		}
 	}
 	
 	//取得多维数组最大值
 	function getMaxdata(arr)
 	{
	 	var maxdata = null;
	 	var mindata = null;
	 	for(i=0;i<arr.length;i++)
	 	{
	 		if(maxdata == null) {
	 			maxdata = d3.max(arr[i], function(d) {return d.value;});
	 		} else {
	 			maxdata=d3.max([maxdata, d3.max(arr[i], function(d) {return d.value;})]);
	 		}
	 		
	 		if(mindata == null) {
	 			mindata = d3.min(arr[i], function(d) {return d.value;});
	 		} else {
	 			mindata = d3.min([mindata, d3.min(arr[i], function(d) {return d.value;})]);
	 		}
	 	}
	 	return {max : maxdata, min : mindata};
 	}
}
window.GroupLineChart = GroupLineChart;